/***************************************************************************
 *   Copyright (C) 2005 by xihe   *
 *   xihels@163.com                                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef _SEND_IM_H_
#define _SEND_IM_H_

#include "Packet.h"
#include "ImPacketFont.h"

/**
 * 发送消息的包，格式为
 * 1. 头部
 * 2. 发送者QQ号，4个字节
 * 3. 接收者的QQ号，4个字节
 * 4. 发送者QQ版本，2字节
 * 5. 发送者QQ号，4字节
 * 6. 接收者QQ号，4个字节（奇怪，为什么要搞两个在里面）
 * 7. 发送者QQ号和session key合在一起用md5处理一次的结果，16字节
 * 8. 消息类型，2字节
 * 9. 会话ID，2字节，如果是一个操作需要发送多个包才能完成，则这个id必须一致
 * 10. 发送时间，4字节
 * 11. 发送者头像，2字节
 * 12. 字体信息，4字节，设成0x00000001吧，不懂具体意思
 * 13. 消息分片数，1字节，如果消息比较长，这里要置一个分片值，
 * QQ缺省是700字节一个分片，这个700字节是纯消息，
 *     不包含其他部分
 * 14. 分片序号，从0开始
 * 15. 消息的id，2字节，同一条消息的不同分片id相同
 * 17. 消息方式，是发送的，还是自动回复的，1字节
 * 18. 消息内容
 * 19. 空格和0x0
 * 20. 消息的尾部，包含一些消息的参数，比如字体颜色啦，等等等等，顺序是
 *     1. 字体修饰属性，bold，italic之类的，1字节，具体的设置是
 *         i.   bit0-bit4用来表示字体大小，所以最大是32
 *         ii.  bit5表示是否bold
 *         iii. bit6表示是否italic
 *         iv.  bit7表示是否underline
 *     2. 颜色Red，1字节
 *     3. 颜色Green，1字节
 *     4. 颜色Blue，1字节
 *     5. 1个未知字节，置0先
 *     6. 消息编码，2字节，0x8602为GB，0x0000为EN，
 *     其他未知，好像可以自定义，因为服务器好像不干涉
 *     7. 可变长度的一段信息，字体名后面跟一个回车符，比如0xcb, 0xce, 0xcc, 0xe5表示宋体 
 * 21. 1字节，表示19和20部分的字节长度
 * 22. 包尾部
 *
 * 请求传送文件的包，这是这个包的另一种用法，其格式为
 * 1  - 14. 1到15部分均与发送消息包相同，只有第8部分不同，
 * 对于UDP的请求，8部分是0x0035，对于TCP，是0x0001
 * 15 - 17. 怀疑也和发送消息包相同，但是在这种情况中，这部分没有使用，为全0，一共11个0字节
 * 18. 传输类型，1字节，表示是传文件还是传表情
 * 19. 连接方式字节，UDP是0， TCP是3
 * 20. 4个字节的发送者外部ip地址（也就是可能为代理地址）
 * 21. 2个字节的发送者端口
 * 22. 2个字节的端口，第一个监听端口，TCP没有这个部分
 * 23. 4个字节的地址，真实IP
 * 24. 2个字节的端口，第二个监听端口
 * 25. 空格符号做为上述信息的结束，一个字节，0x20
 * 26. 分隔符0x1F
 * 27. 要传送的文件名
 * 28. 分隔符0x1F
 * 29. 字节数的字符串形式后跟" 字节"
 * ，比如文件大小3字节的话，就是"3 字节"这个字符串的编码形式
 * 30. 尾部 
 * 
 * 同意传送文件的包，格式为
 * 1  - 24. 除了8部分，其他均与发送消息包相同。对于UDP的情况，8部分是0x0037，TCP是0x0003。
 *          UDP时，最后的本地ip和端口都是0；TCP时没有22部分
 * 25. 尾部
 * 
 * 拒绝接收文件的包，格式为
 * 1 - 19. 除了8部分，均与同意传送文件包相同。
 * 对于UDP的情况，8部分是0x0039，对于TCP，是0x0005
 * 20. 尾部
 * 
 * 通知我的IP信息，格式为
 * 1 - 24. 除了8部分，均与请求传送文件包相同。8部分是0x003B
 * 25. 尾部
 * 
 * 取消传送文件，格式为
* 1 - 18. 除了8部分，均与请求传送文件包相同。8部分是0x0049
* 19. 尾部
* 
* 要求别人主动连接我的包，格式为
* 1 - 18. 除了8部分，均与请求传送文件包相同。8部分是0x003F
* 19. 尾部
*/

class SendIMPacket : public OutPacket {
    public:
	SendIMPacket(QQClient& cl, 
		const string msg, 
		uint32_t _receiver, 
		uint16_t _messageId = 0,
		uint8_t  _fragmentSequence = 0,
		uint8_t  _replyType = QQ_IM_NORMAL_REPLY);
	int putBody(uint8_t* buf) const;

	void setTotalFragments(uint8_t _totalFragments)
       	{ totalFragments = _totalFragments; }

    private:
	ImPacketFont font;
	string	 message;
	uint32_t receiver;	    // 接收者QQ号
	uint16_t messageType;
	uint16_t messageId;
	uint8_t  totalFragments;
	uint8_t  fragmentSequence;
	uint8_t	 replyType;	    
};

/**
  发送消息的回复消息，格式为
  1. 头部
  2. 一个字节的应答码，0表示成功
  3. 尾部
  */

class SendIMReplyPacket : public InPacket {
    protected:
	SendIMReplyPacket(const uint8_t* buf, int len):
	    InPacket(buf, len, true),
	    replyCode(*(buf + QQ_HEADER_LENGTH_BASIC_FAMILY_IN))
	{}
    public:
	uint8_t getReplyCode() const { return replyCode; }
    private:
	uint8_t replyCode;
};
#endif // _SEND_IM_H_

